package org.codehaus.activemq.util;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Map;

public class FactoryFinder
{
  private String path;
  private Map classes = new HashMap();

  public FactoryFinder(String path) {
    this.path = path;
  }

  public Object newInstance(String key)
    throws IllegalAccessException, InstantiationException, IOException, ClassNotFoundException
  {
    Class type = findClass(key);
    return type.newInstance();
  }

  public Class findClass(String key)
    throws IOException, ClassNotFoundException
  {
    Class answer = (Class)this.classes.get(key);
    if (answer == null) {
      answer = doFindClass(key);
      this.classes.put(key, answer);
    }
    return answer;
  }

  private Class doFindClass(String key) throws IOException, ClassNotFoundException
  {
    String uri = this.path + key;

    InputStream in = Thread.currentThread().getContextClassLoader().getResourceAsStream(uri);
    if (in == null) {
      in = getClass().getClassLoader().getResourceAsStream(uri);
      if (in == null) {
        throw new IOException("Could not find class for resource: " + uri);
      }
    }

    try
    {
      BufferedReader reader = new BufferedReader(new InputStreamReader(in));
      String line = reader.readLine();
      if (line == null) {
        throw new IOException("Empty file found for: " + uri);
      }
      line = line.trim();
      Class answer = loadClass(line);
      if (answer == null) {
        throw new ClassNotFoundException("Could not find class: " + line);
      }
      Class localClass1 = answer;
      return localClass1;
    }
    finally
    {
      try
      {
        in.close();
      } catch (Exception e) {
    	  throw e;
      }
    }
    
  }

  protected Class loadClass(String name) throws ClassNotFoundException
  {
    try {
      return Thread.currentThread().getContextClassLoader().loadClass(name);
    } catch (ClassNotFoundException e) {
    }
    return getClass().getClassLoader().loadClass(name);
  }
}